#!/usr/bin/env python
"""mon_center.py -- main program of the monitor subsystem on the center

"""

from Queue import Queue
import threading
import xmlrpclib
import socket
import time
import os
import sys

from daemonize import startstop

from data_reciever import DataReciever
from data_processor import DataProcessor
from mon_center_base import ThreadingXMLRPCServer
from mon_center_utils import decode, error_handler, \
                            get_ip_address, threadinglize, getDictDeeply, \
                            delDictDeeply
#from mon_rw_handler import TimelyDataRWHandler
from mon_db_handler import MonDBHandler
import mon_center_logger
from mon_session import *
from mon_config_manager import global_config

logger = mon_center_logger.instance()

curdir = os.path.dirname(os.path.abspath(__file__))
DEFAULT_CONF = curdir + os.path.sep + "center_default_config"


def start_data_getter_thread(address):
    #dataReciever = UDPServer(address, DRRequestHandler)
    dataReciever = DataReciever(address, queue)
    logger.info('data-reciever running on port %d' % address[1])
    dataReciever.serve_forever() 


start_data_getter = threadinglize(start_data_getter_thread, 'data_getter')

def build_metadata(host, metadata, db_handler):
    #print metadata
    hostid = getidbyip(host)
    db_handler.write(hostid, "metadata", metadata)



   
class Controller(object):
    
    def __init__(self, config):
        self._config = config

    def _listMethod(self):
        return []

    def ping(self):
        return 'pong'

    def sign_in(self, message):
        metadata = decode(message)
        logger.debug('%s' % (metadata,))
        host = metadata['listen_channel']['host']
        port = metadata['listen_channel']['port']
        logger.info('%s try to sign in' % (host,))
        #found = None
        #node_list = global_config['node_list']
        #for hostspec in node_list:
            #if host == hostspec['host']:
                #found = host
                #break
        #if not found:
            #return False
        set_session(host, port=port, state='touched') 
        try:
            build_metadata(host, message, dbhandler)
        except Exception, e:
            logger.exception('')
            return False
        else:
            set_session(host, state='ready')
            logger.info('%s signed in' % host)
            return True

    def vm_sign_in(self, message):
        metadata = decode(message)
        logger.debug('%s' % (metadata,))
        host = metadata['listen_channel']['host']
        port = metadata['listen_channel']['port']
        logger.info('vm %s try to sign in' % (host,))
        if (get_session(host) is None) or (get_session(host, 'type') != 'vm'):
            logger.error('unregistered vm %s' % host)
            return False
        set_session(host, port=port, state='touched') 
        try:
            build_metadata(host, message, dbhandler)
        except Exception, e:
            logger.exception('')
            return False
        else:
            set_session(host, state='ready')
            logger.info('vm %s signed in' % host)
            return True
        

    def on_vm_create(self, vm_id, vm_addr):
        try:
            set_session(vm_addr, type='vm', id=vm_id)
            return True
        except Exception, e:
            logger.exception('')
            return False

    def on_vm_shutdown(self, vm_id, vm_addr):
        try:
            unset_session(vm_addr)
            return True
        except Exception, e:
            logger.exception('')
            return False



def main():

    #global global_config
    global dbhandler
    global queue

    #global_config = load_config(DEFAULT_CONF)
    queue = Queue()

    host = get_ip_address('eth0')
    port = global_config['listen_channel']['port']
    addr = (host, port)
    start_data_getter(addr)

    dbhandler = MonDBHandler.getInstance(global_config['db']['root_dir'])

    data_processor = DataProcessor(queue, dbhandler)
    data_processor.start()

    server = ThreadingXMLRPCServer(addr)
    server.register_introspection_functions()
    server.register_instance(Controller(global_config))
    logger.info('running server on port: %d' % addr[1])
    server.serve_forever()


if __name__ == "__main__":
    ofile = global_config['ofile']
    pfile = global_config['pfile']
    startstop(stdout=ofile, pidfile=pfile)
    main()
